// 安装依赖 pnpm add -D @babel/core @types/babel-types @types/babel__core @types/babel__traverse babel-traverse babel-types magic-string
import {ConfigEnv, Plugin, TransformResult, UserConfig, ViteDevServer} from 'vite';
import {CallExpression} from "babel-types";
import {NodePath} from "@babel/traverse";
import Utils from "../utils";
import {FileListen} from "../utils/FileListen";
import * as fs from 'fs'
import * as path from "path";

export default function vitePluginRequireChange(includes: string[] = [], excludes: string[] = []): Plugin {
  let extensions: string[] = []
  const valPre = '__zhixin__transform__require__'
  let count = 0
  let alias = {}
  let server: ViteDevServer
  return {
    name: "vite:vite-plugin-require-change",
    config(config: UserConfig, env: ConfigEnv): UserConfig | void | Promise<UserConfig | void | null> | null {
      extensions = config.resolve.extensions;
      // 获取别名路径
      alias = Utils.getAliasPath(config)
      return config;
    },
    configureServer(_server) {
      server = _server
    },
    transform(code: string, id: string): Promise<TransformResult> | TransformResult {
      let map = null
      if (id.includes('node_modules') && !includes.some(item => id.includes(item)) || excludes.some(item => id.includes(item))) {
        return {code, map}
      }
      if (/.js$|.jsx$|.ts$|.tsx$|.vue$/.test(id)) {
        const ast = Utils.getJsAst(code)
        const s = Utils.getMagicString(code)
        Utils.jsAstTraverse(ast, {
          CallExpression(ipath: NodePath<CallExpression>) {
            const node = ipath.node;
            const callee = node.callee;
            const arguments2 = node.arguments;
            if (callee.type === 'Identifier') {
              if (callee?.name === 'require') { // 支持require
                if (arguments2.length === 1) {
                  const arg0 = arguments2[0]
                  const pathNotVar = Utils.pathNotVar(arg0);
                  if (pathNotVar.notVar) { // require('ssssss)
                    const valName = (valPre + count++)
                    s.prepend(`import * as ${valName} from '${pathNotVar.value}';\n`)
                    s.overwrite(node.start, node.end, `${valName}.default?${valName}.default:${valName}`)
                  } else { // require('ssss'+test) require(`sss${test}`)
                    let basePath = ''
                    let oldBasePath = ''
                    let endPath = ''
                    if (arg0.type === 'TemplateLiteral') {
                      oldBasePath = basePath = arg0.quasis[0].value.raw
                      endPath = arg0.quasis[arg0.quasis.length - 1].value.raw
                    } else if (arg0.type === 'BinaryExpression') {
                      oldBasePath = basePath = Utils.binaryExpressionGeBesttLeft(arg0)
                      endPath = Utils.binaryExpressionGeBesttRight(arg0)
                    }
                    basePath = Utils.getBasePath(alias, id, basePath)
                    // require('./env.' + environment) 处理这种情况
                    let perName = ''
                    if(!fs.existsSync(basePath)) {
                      perName = oldBasePath
                      basePath = path.join(basePath, '..').replace(/\\/g,'/')
                    }
                    FileListen.viteAddDirListen(basePath, id, server)
                    if (!oldBasePath.endsWith('/')) {
                      oldBasePath = oldBasePath + '/'
                    }
                    const files = Utils.readDirectory(basePath, true, new RegExp(endPath));
                    let all = ''
                    Object.keys(files).forEach(key => {
                      if(!perName || !key.startsWith(perName)) {
                        return
                      }
                      const valName = (valPre + count++)
                      s.prepend(`import * as ${valName} from '${files[key]}';\n`)
                      all += `'${key.replace('./', oldBasePath).substring(perName.length)}': ${valName},`
                    })
                    const arg0Str = s.slice(arg0.start, arg0.end)
                    let changeValue = Utils.transCodePathFilesAsync(all, extensions, arg0Str, Utils.nodeAddFenge(ipath.parent))
                    s.overwrite(node.start, node.end, changeValue)
                  }
                } else if (arguments2.length === 2) {
                  const arguments2Element0 = arguments2[0];
                  if (arguments2Element0.type === 'ArrayExpression') { // 返回的是异步的 ===> import()
                    const element = arguments2Element0.elements[0];
                    const arg = code.slice(element.start, element.end)
                    s.overwrite(node.start, node.end, `import(${arg})`)
                  }
                }
              }
            }
          },
        })
        map = Utils.getsouceMap(s, code)
        code = s.toString()
      }
      return {
        code,
        map
      };
    },
  }
}

// 支持require('5555') 或者 require('sss'+test)

// 支持require([`@/views/select-object/${dynamicImport}`], resolve)
